package com.rbac.common.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.rbac.application.service.UserService;
import com.rbac.common.annotation.RequirePermission;
import com.rbac.common.exception.AuthException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class PermissionAspect {

    private final UserService userService;

    @Pointcut("@annotation(com.rbac.common.annotation.RequirePermission)")
    public void permissionPointcut() {}

    @Around("permissionPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 检查是否已登录
        if (!StpUtil.isLogin()) {
            throw new AuthException("请先登录");
        }
        
        // 获取当前用户ID
        Long userId = StpUtil.getLoginIdAsLong();
        
        // 超级管理员直接放行
        if (userId.equals(1L)) {
            return joinPoint.proceed();
        }
        
        // 获取注解信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequirePermission annotation = method.getAnnotation(RequirePermission.class);
        
        if (annotation == null) {
            return joinPoint.proceed();
        }
        
        // 获取用户权限
        List<String> userPermissions = userService.getUserPermissions(userId);
        
        // 解析需要的权限
        String[] requiredPermissions = annotation.value().split(",");
        
        // 检查权限
        boolean hasPermission = checkPermissions(userPermissions, requiredPermissions, annotation.mode());
        
        if (!hasPermission) {
            log.warn("用户[{}]访问方法[{}]权限不足，需要权限：{}", 
                    userId, method.getName(), Arrays.toString(requiredPermissions));
            throw new AuthException("权限不足，无法访问");
        }
        
        return joinPoint.proceed();
    }
    
    /**
     * 检查权限
     */
    private boolean checkPermissions(List<String> userPermissions, String[] requiredPermissions, RequirePermission.Mode mode) {
        if (requiredPermissions.length == 0) {
            return true;
        }
        
        if (mode == RequirePermission.Mode.AND) {
            // AND模式：需要拥有所有权限
            return Arrays.stream(requiredPermissions)
                    .allMatch(permission -> userPermissions.contains(permission.trim()));
        } else {
            // OR模式：只需要拥有其中一个权限
            return Arrays.stream(requiredPermissions)
                    .anyMatch(permission -> userPermissions.contains(permission.trim()));
        }
    }
}